#include <windows.h>
#include "TBRwindowApplication.h"


using namespace TBR;
	//mouse
const int TBR::WindowApplication::MOUSE_LB = 0;
const int TBR::WindowApplication::MOUSE_MB = 1;
const int TBR::WindowApplication::MOUSE_RB = 2;

const int TBR::WindowApplication::MODIFIER_CONTROL = MK_CONTROL;
const int TBR::WindowApplication::MODIFIER_LB = MK_LBUTTON;
const int TBR::WindowApplication::MODIFIER_MB = MK_MBUTTON;
const int TBR::WindowApplication::MODIFIER_RB = MK_RBUTTON;
const int TBR::WindowApplication::MODIFIER_SHIFT = MK_SHIFT;



void WindowApplication::setMousePosition(int x, int y)
{
    HWND handle = (HWND)IntToPtr(_windowID);
    POINT point;
    point.x = (LONG)x;
    point.y = (LONG)y;
    ClientToScreen(handle, &point);
    SetCursorPos(point.x, point.y);
}

void WindowApplication::getMousePosition(int& x, int& y) 
{
    HWND handle = (HWND)IntToPtr(_windowID);
    POINT point;
    GetCursorPos(&point);
    ScreenToClient(handle, &point);
    x = (int)point.x;
    y = (int)point.y;
}

static bool gsIgnoreWindowDestroy = false;

LRESULT CALLBACK MsWindowEventHandler (HWND handle, UINT message,
    WPARAM wParam, LPARAM lParam)
{
    WindowApplication* theApp = (WindowApplication*)Application::TheApplication;

    if (!theApp || !theApp->getWindowID())
    {
        return DefWindowProc(handle, message, wParam, lParam);
    }

    switch (message) 
    {
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            BeginPaint(handle, &ps);
            //theApp->onDisplay();
            EndPaint(handle, &ps);
            return 0;
        }
        case WM_ERASEBKGND:
        {
            // This tells Windows not to erase the background (and that the
            // application is doing so).
            return 1;
        }
        case WM_DESTROY:
        {
            // The DestroyWindow call when recreating the window for
            // multisampling causes the application to terminate.  It is
            // not clear why the same problem did not occur in WM4.
            if (!gsIgnoreWindowDestroy)
            {
                PostQuitMessage(0);
            }
            gsIgnoreWindowDestroy = false;
            return 0;
        }
	}

	return DefWindowProc(handle, message, wParam, lParam);

}


int WindowApplication::windowMain(int, char **)
{
    WindowApplication* theApp = (WindowApplication*)TheApplication;

    // === Create the window for rendering. ===

    // Register the window class.
    static char sWindowClass[] = "Wild Magic 5 Application";
    WNDCLASS wc;
    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc   = MsWindowEventHandler;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = 0;
    wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszClassName = sWindowClass;
    wc.lpszMenuName  = 0;
    RegisterClass(&wc);

    // Require the window to have the specified client area.
    RECT rect = { 0, 0, theApp->getWidth()-1, theApp->getHeight()-1 };
    AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);

    // Create the application window.
    HWND handle = CreateWindow(sWindowClass, theApp->getWindowTitle(),
        WS_OVERLAPPEDWINDOW, theApp->getxPos(), theApp->getyPos(),
        rect.right - rect.left + 1, rect.bottom - rect.top + 1, 0, 0, 0, 0);

    // Save the handle as an 'int' for portable handle storage.
    theApp->setWindowID(PtrToInt(handle));

    // ===
    if (theApp->onInitialize())
    {
        // The default OnPreidle() clears the buffers.  Allow the application
        // to fill them before the window is shown and before the event loop
        // starts.
        //theApp->OnPreidle();

        // Display the window.
        ShowWindow(handle, SW_SHOW);
        UpdateWindow(handle);

        // Start the message pump.
        bool applicationRunning = true;
        while (applicationRunning)
        {
            MSG msg;
            if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                if (msg.message == WM_QUIT)
                {
                    applicationRunning = false;
                    continue;
                }

                HACCEL accel = 0;
                if (!TranslateAccelerator(handle, accel, &msg))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
            else
            {
                theApp->onIdle(); //do rendering stuff
            }
        }
    }
    theApp->onTerminate();


	return 0;
	//
}
